1 Introduction

Sampling distributions form the cornerstone of statistical inference. They describe the probability distribution of a sample statistic calculated from random samples. This note explores both exact (finite-sample) and asymptotic (large-sample) distributions for key statistics including sample means, proportions, and related test statistics.

2 Sampling Distribution of the Sample Mean

When the population is normal, by the property of normal distribution, the sum of the iid random variables are exactly normally distributed. If the population is not a normal distribution, using the Central Limit Theorem (CLT), the sum of the iid random variables is asymptotically normally distributed.

2.1 Exact Distribution

For a random sample \(X_1, X_2, \ldots, X_n\) from a normal population \(N(\mu, \sigma^2)\), the sample mean has an exact normal distribution:

\[ \bar{X} \to N\left(\mu, \frac{\sigma}{\sqrt{n}}\right) \]

The standardized version is:

\[ Z = \frac{\bar{X}-\mu}{\sigma/\sqrt{n}} \to N(0, 1) \]

Example:

set.seed(123)
n <- 10
mu <- 5
sigma <- 2

n.samples <- 10000
sample.means <- replicate(n.samples, mean(rnorm(n, mu, sigma)))

# Create theoretical curve data
x.vals <- seq(mu - 3*sigma/sqrt(n), mu + 3*sigma/sqrt(n), length.out = 100)
theory.density <- dnorm(x.vals, mean = mu, sd = sigma/sqrt(n))
theory.df <- data.frame(x = x.vals, density = theory.density)

xbar.plt <- ggplot(data.frame(mean = sample.means), aes(x = mean)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "gray") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  labs(title = "Exact Sampling Distribution of Sample Mean \nNormal Population (n = 10)",
       x = "Sample Mean", y = "Density") +
   theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))

ggplotly(xbar.plt)

2.2 Asymptotic Distribution (Central Limit Theorem)

For any population with finite mean \(\mu\) and variance \(\sigma^2\), as \(n \to \infty\):

\[ Z = \frac{\bar{X}-\mu}{\sigma/\sqrt{n}} \to_{\text{approx}} N(0, 1) \]

Example Consider exponential population:

set.seed(123)
n.large <- 50
lambda <- 1/5  # Mean = 5

# Generate multiple samples from exponential distribution
n.samples <- 10000
exp.means <- replicate(n.samples, mean(rexp(n.large, rate = lambda)))

# Compare with normal approximation
theoretical.mean <- 1/lambda  # 5
theoretical.sd <- (1/lambda)/sqrt(n.large)  # 5/sqrt(50)

theory.density <- dnorm(x.vals, mean = theoretical.mean, sd = theoretical.sd)
theory.df <- data.frame(x = x.vals, density = theory.density)

# Option 1: Use only stat_function for theoretical curve (Recommended)
gg.clt <- ggplot(data.frame(mean = exp.means), aes(x = mean)) +
  geom_histogram(aes(y = after_stat(density)), bins = 50, alpha = 0.7, fill = "lightgreen") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  labs(title = "Asymptotic Sampling Distribution of Sample Mean \nExponential Population (n = 50)",
       x = "Sample Mean", y = "Density") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
#gg.clt
ggplotly(gg.clt)

3 Student’s t-Distribution

When population variance \(\sigma^2\) is unknown and estimated by sample variance \(S^2\):

\[ T = \frac{\bar{X}-\mu}{S/\sqrt{n}} \to t_{n-1} \]

where \(S^2 = \frac{1}{n-1}\sum_{i=1}^n (X_i - \bar{X})^2\)

Example:

set.seed(123)
n <- 10
mu <- 5
sigma <- 2

# Generate t-statistics
n.samples <- 10000
t.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  sample.data <- rnorm(n, mu, sigma)
  x.bar <- mean(sample.data)
  s <- sd(sample.data)
  t.stats[i] <- (x.bar - mu) / (s/sqrt(n))
}

# Compare with theoretical t-distribution
x.vals <- seq(-4, 4, length.out = 200)
theoretical.t <- dt(x.vals, df = n-1)
theoretical.normal <- dnorm(x.vals)

comparison.df <- data.frame(
  x = rep(x.vals, 2),
  density = c(theoretical.t, theoretical.normal),
  distribution = rep(c("t(9)", "N(0,1)"), each = length(x.vals))
)

t.plt <- ggplot(comparison.df, aes(x = x, y = density, color = distribution)) +
  geom_line(size = 1) +
  labs(title = "t-Distribution vs Normal Distribution",
       x = "Value", y = "Density") +
    theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt")) +
   scale_color_manual(values = c("red", "blue"))
ggplotly(t.plt)

4 Sampling Distribution of Sample Proportion

3.1 Exact Distribution

For a binomial population with success probability \(p\), the sample proportion \(\hat{p} = X/n\) where \(X \sim Binomial(n,p)\).

The exact distribution is simply the probability mass function of a binomial distribution with n trials and success probability \(p\):

\[ P(\hat{p} =k/n)=P(X = k)=\frac{n!}{k!(n-k)!} p^k (1−p)^{n-k}, \ \ k = 0, 1, 2, \cdots, n. \]

4.1 Asymptotic Distribution

By Central Limit Theorem, as \(n \to \infty\):

\[ \hat{p} \to N\left(p, \sqrt{\frac{p(1-p)}{n}} \right) \]

Example:

set.seed(123)
n <- 100
p <- 0.3

# Generate sample proportions
n.samples <- 10000
sample.props <- replicate(n.samples, rbinom(1, n, p)/n)

# Compare with normal approximation
theoretical.mean <- p
theoretical.sd <- sqrt(p*(1-p)/n)

x.vals <- seq(0,0.6, length=100)
theory.density <- dnorm(x.vals, mean = theoretical.mean, sd = theoretical.sd)
theory.df <- data.frame(x = x.vals, density = theory.density)

binom.plt <- ggplot(data.frame(prop = sample.props), aes(x = prop)) +
  geom_histogram(aes(y = ..density..), bins = 30, alpha = 0.7, fill = "skyblue") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  #stat_function(fun = dnorm, 
  #              args = list(mean = theoretical_mean, sd = theoretical_sd),
  #              color = "red", size = 1) +
  labs(title = "Sampling Distribution of Sample Proportion",
       subtitle = "p = 0.3, n = 100",
       x = "Sample Proportion", y = "Density") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(binom.plt)

5 Chi-Square Distribution

For \(Z_1, Z_2, \ldots, Z_k \stackrel{iid}{\sim} N(0,1)\), using moment generating function, we can show that

\[ Q=\sum_{i=1}^k Z_i^2 \to \chi_k^2. \]

For sample variance from normal population:

\[ \frac{(n-1)S^2}{\sigma^2} \to \chi_{n-1}^2 \] Proof: We prove this in several steps:

We show that for \(X_1, \dots, X_n \iid N(\mu, \sigma^2)\), with

\[ S^2 = \frac{1}{n-1} \sum_{i=1}^n (X_i - \bar{X})^2, \quad \bar{X} = \frac{1}{n} \sum_{i=1}^n X_i, \]

we have

\[ \frac{(n-1)S^2}{\sigma^2} \sim \chi_{n-1}^2. \]

Step 1: Standardize and define notation

Let \(Z_i = \frac{X_i - \mu}{\sigma} \sim N(0,1)\), i.i.d. Then

\[ \bar{Z} = \frac{1}{n} \sum_{i=1}^n Z_i = \frac{\bar{X} - \mu}{\sigma}. \]

We can write:

\[ \sum_{i=1}^n (X_i - \bar{X})^2 = \sigma^2 \sum_{i=1}^n (Z_i - \bar{Z})^2. \]

So

\[ \frac{(n-1)S^2}{\sigma^2} = \frac{\sum_{i=1}^n (X_i - \bar{X})^2}{\sigma^2} = \sum_{i=1}^n (Z_i - \bar{Z})^2. \]

Step 2: Orthogonal transformation

Let \(\mathbf{Z} = (Z_1, \dots, Z_n)^T\). Choose an \(n \times n\) orthogonal matrix \(Q\) whose first row is \(\left( \frac{1}{\sqrt{n}}, \dots, \frac{1}{\sqrt{n}} \right)\). Define

\[ \mathbf{Y} = Q \mathbf{Z}. \]

Then:

  • \(Y_1 = \frac{1}{\sqrt{n}} \sum_{i=1}^n Z_i = \sqrt{n} \, \bar{Z}\).
  • Since \(Q\) is orthogonal and \(\mathbf{Z} \sim N(0, I_n)\), we have \(\mathbf{Y} \sim N(0, I_n)\) as well, so \(Y_1, \dots, Y_n\) are i.i.d. \(N(0,1)\).

Step 3: Express sum of squares in terms of \(Y_j\)

Orthogonality implies:

\[ \sum_{i=1}^n Z_i^2 = \sum_{j=1}^n Y_j^2. \]

Also,

\[ \sum_{i=1}^n (Z_i - \bar{Z})^2 = \sum_{i=1}^n Z_i^2 - n \bar{Z}^2. \]

But \(n \bar{Z}^2 = Y_1^2\), so

\[ \sum_{i=1}^n (Z_i - \bar{Z})^2 = \sum_{j=1}^n Y_j^2 - Y_1^2 = \sum_{j=2}^n Y_j^2. \]

Step 4: Distribution

Since \(Y_2, \dots, Y_n\) are i.i.d. \(N(0,1)\), we have

\[ \sum_{j=2}^n Y_j^2 \sim \chi_{n-1}^2. \]

Thus

\[ \frac{(n-1)S^2}{\sigma^2} = \sum_{i=1}^n (Z_i - \bar{Z})^2 = \sum_{j=2}^n Y_j^2 \sim \chi_{n-1}^2. \]

Step 5: Independence from \(\bar{X}\)

Since \(Y_1 = \sqrt{n} \bar{Z}\) is independent of \(Y_2, \dots, Y_n\), it follows that \(\bar{X}\) is independent of \(S^2\). That is,

\[ \boxed{\frac{(n-1)S^2}{\sigma^2} \to \chi_{n-1}^2} \]

Example: The \(\chi^2\) distribution is derived from the standard normal distribution. We simulate standard normal random numbers and then transform them into \(\chi^2\) random variables based on the derivations above. A histogram will be plotted and overlaid with the theoretical \(\chi^2\) density curve.

set.seed(123)
n <- 10
sigma <- 2

# Generate chi-square statistics
n.samples <- 10000
chisq.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  sample.data <- rnorm(n, 0, sigma)
  chisq.stats[i] <- sum((sample.data/sigma)^2)
}

# Compare with theoretical chi-square
x.vals <- seq(0, 30, length.out = 200)
theoretical.chisq <- dchisq(x.vals, df = n)
theory.df <- data.frame(x = x.vals, density = theoretical.chisq)

chi.plt <- ggplot(data.frame(x = chisq.stats), aes(x = x)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "steelblue") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  #stat_function(fun = dchisq, args = list(df = n), color = "red", size = 1) +
  labs(title = "Chi-Square Distribution",
       subtitle = "Sum of squared standard normals",
       x = "Value", y = "Density") +
   theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(chi.plt)

6 F-Distribution

For two independent chi-square random variables:

\[ F = \frac{U_1/d_1}{U_2/d_2} \to F_{d_1, d_2} \]

where \(U_1 \sim \chi^2_{d_1}\) and \(U_2 \sim \chi^2_{d_2}\).

F distribution is used for comparing variances: \(\frac{S_1^2/\sigma_1^2}{S_2^2/\sigma_2^2} \sim F_{n_1-1,n_2-1}\). For example, if we test

\[ H_0: \ \sigma_1 = \sigma_2 \ \ \ v.s. \ \ \ H_a: \sigma_1 \ne \sigma_2 \] The test statistic

\[ TS = \frac{S_1^2}{S_2^2} \to F_{n_1-1, n_2-1} \]

Example: The F distribution is directly defined based on two independent \(\chi^2\) distributions, which are themselves derived from standard normal distributions. Therefore, we could generate data from normal distributions and then transform them into F random variables. To keep the process simple, we generate data directly from \(\chi^2\) distributions.

set.seed(123)
df1 <- 10
df2 <- 15

# Generate F statistics
n.samples <- 10000
f.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  u1 <- rchisq(1, df1)
  u2 <- rchisq(1, df2)
  f.stats[i] <- (u1/df1) / (u2/df2)
}

# Compare with theoretical F-distribution
x.vals <- seq(0, 5, length.out = 200)
theoretical.f <- df(x.vals, df1, df2)
theory.df <- data.frame(x = x.vals, density = theoretical.f)




f.plt <- ggplot(data.frame(x = f.stats), aes(x = x)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "purple3") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  coord_cartesian(xlim = c(0, 5)) +
  labs(title = paste("F-Distribution \n F(", df1, ",", df2, ")", sep = ""),
       x = "Value", y = "Density") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(f.plt)

7 Summary of Key Relationships

Statistic Exact Distribution Asymptotic Distribution Conditions
\(\bar{X}\) \(N(\mu, \sigma^2/n)\) \(N(\mu, \sigma^2/n)\) Normal population or large n
\(\frac{\bar{X}-\mu}{S/\sqrt{n}}\) \(t_{n-1}\) \(N(0,1)\) Normal population
\(\hat{p}\) \(Binomial(n,p)/n\) \(N(p, p(1-p)/n)\) \(np, n(1-p) \geq 5\)
\(\frac{(n-1)S^2}{\sigma^2}\) \(\chi^2_{n-1}\) - Normal population
\(\frac{S_1^2/\sigma_1^2}{S_2^2/\sigma_2^2}\) \(F_{n_1-1,n_2-1}\) - Normal populations

Conclusion

  • Understanding sampling distributions is fundamental to statistical inference:

  • Exact distributions provide precise results when assumptions are met

  • Asymptotic distributions offer approximations for large samples

  • The choice between exact and asymptotic methods depends on sample size, distributional assumptions, and the specific parameter being estimated

  • Modern computing allows for empirical verification of these theoretical results

These distributions form the theoretical foundation for hypothesis testing, confidence intervals, and many other statistical procedures.

LS0tDQp0aXRsZTogIlNhbXBsaW5nIERpc3RyaWJ1dGlvbnMiDQphdXRob3I6ICJDaGVuZyBQZW5nIg0KZGF0ZTogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCg0KIyMgbGlicmFyeShsZWFwcykNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQoNClwNCg0KDQojIEludHJvZHVjdGlvbg0KDQpTYW1wbGluZyBkaXN0cmlidXRpb25zIGZvcm0gdGhlIGNvcm5lcnN0b25lIG9mIHN0YXRpc3RpY2FsIGluZmVyZW5jZS4gVGhleSBkZXNjcmliZSB0aGUgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIG9mIGEgKipzYW1wbGUgc3RhdGlzdGljKiogY2FsY3VsYXRlZCBmcm9tIHJhbmRvbSBzYW1wbGVzLiBUaGlzIG5vdGUgZXhwbG9yZXMgYm90aCBleGFjdCAoZmluaXRlLXNhbXBsZSkgYW5kIGFzeW1wdG90aWMgKGxhcmdlLXNhbXBsZSkgZGlzdHJpYnV0aW9ucyBmb3Iga2V5IHN0YXRpc3RpY3MgaW5jbHVkaW5nIHNhbXBsZSBtZWFucywgcHJvcG9ydGlvbnMsIGFuZCByZWxhdGVkIHRlc3Qgc3RhdGlzdGljcy4NCg0KDQojIFNhbXBsaW5nIERpc3RyaWJ1dGlvbiBvZiB0aGUgU2FtcGxlIE1lYW4NCg0KV2hlbiB0aGUgcG9wdWxhdGlvbiBpcyBub3JtYWwsIGJ5IHRoZSBwcm9wZXJ0eSBvZiBub3JtYWwgZGlzdHJpYnV0aW9uLCB0aGUgc3VtIG9mIHRoZSBpaWQgcmFuZG9tIHZhcmlhYmxlcyBhcmUgKipleGFjdGx5Kiogbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIElmIHRoZSBwb3B1bGF0aW9uIGlzIG5vdCBhIG5vcm1hbCBkaXN0cmlidXRpb24sIHVzaW5nIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gKENMVCksIHRoZSBzdW0gb2YgdGhlIGlpZCByYW5kb20gdmFyaWFibGVzIGlzICoqYXN5bXB0b3RpY2FsbHkqKiBub3JtYWxseSBkaXN0cmlidXRlZC4NCg0KDQojIyBFeGFjdCBEaXN0cmlidXRpb24NCg0KRm9yIGEgcmFuZG9tIHNhbXBsZSAkWF8xLCBYXzIsIFxsZG90cywgWF9uJCBmcm9tIGEgbm9ybWFsIHBvcHVsYXRpb24gJE4oXG11LCBcc2lnbWFeMikkLCB0aGUgc2FtcGxlIG1lYW4gaGFzIGFuIGV4YWN0IG5vcm1hbCBkaXN0cmlidXRpb246DQoNCiQkDQpcYmFye1h9IFx0byBOXGxlZnQoXG11LCAgXGZyYWN7XHNpZ21hfXtcc3FydHtufX1ccmlnaHQpDQokJA0KDQpUaGUgc3RhbmRhcmRpemVkIHZlcnNpb24gaXM6DQoNCiQkDQpaID0gXGZyYWN7XGJhcntYfS1cbXV9e1xzaWdtYS9cc3FydHtufX0gXHRvIE4oMCwgMSkNCiQkDQoNCioqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCm4gPC0gMTANCm11IDwtIDUNCnNpZ21hIDwtIDINCg0Kbi5zYW1wbGVzIDwtIDEwMDAwDQpzYW1wbGUubWVhbnMgPC0gcmVwbGljYXRlKG4uc2FtcGxlcywgbWVhbihybm9ybShuLCBtdSwgc2lnbWEpKSkNCg0KIyBDcmVhdGUgdGhlb3JldGljYWwgY3VydmUgZGF0YQ0KeC52YWxzIDwtIHNlcShtdSAtIDMqc2lnbWEvc3FydChuKSwgbXUgKyAzKnNpZ21hL3NxcnQobiksIGxlbmd0aC5vdXQgPSAxMDApDQp0aGVvcnkuZGVuc2l0eSA8LSBkbm9ybSh4LnZhbHMsIG1lYW4gPSBtdSwgc2QgPSBzaWdtYS9zcXJ0KG4pKQ0KdGhlb3J5LmRmIDwtIGRhdGEuZnJhbWUoeCA9IHgudmFscywgZGVuc2l0eSA9IHRoZW9yeS5kZW5zaXR5KQ0KDQp4YmFyLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZShtZWFuID0gc2FtcGxlLm1lYW5zKSwgYWVzKHggPSBtZWFuKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlucyA9IDUwLCBhbHBoYSA9IDAuNywgZmlsbCA9ICJncmF5IikgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHRoZW9yeS5kZiwgYWVzKHggPSB4LCB5ID0gZGVuc2l0eSksIA0KICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIkV4YWN0IFNhbXBsaW5nIERpc3RyaWJ1dGlvbiBvZiBTYW1wbGUgTWVhbiBcbk5vcm1hbCBQb3B1bGF0aW9uIChuID0gMTApIiwNCiAgICAgICB4ID0gIlNhbXBsZSBNZWFuIiwgeSA9ICJEZW5zaXR5IikgKw0KICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSAzNSwgciA9IDIwLCBiID0gMzAsIGwgPSAzMCwgdW5pdCA9ICJwdCIpKQ0KDQpnZ3Bsb3RseSh4YmFyLnBsdCkNCg0KYGBgDQoNCg0KIyMgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gKENlbnRyYWwgTGltaXQgVGhlb3JlbSkNCg0KRm9yIGFueSBwb3B1bGF0aW9uIHdpdGggZmluaXRlIG1lYW4gJFxtdSQgYW5kIHZhcmlhbmNlICRcc2lnbWFeMiQsIGFzICRuIFx0byBcaW5mdHkkOg0KDQoNCg0KJCQNClogPSBcZnJhY3tcYmFye1h9LVxtdX17XHNpZ21hL1xzcXJ0e259fSBcdG9fe1x0ZXh0e2FwcHJveH19IE4oMCwgMSkNCiQkDQoNCg0KKipFeGFtcGxlKiogQ29uc2lkZXIgZXhwb25lbnRpYWwgcG9wdWxhdGlvbjoNCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpuLmxhcmdlIDwtIDUwDQpsYW1iZGEgPC0gMS81ICAjIE1lYW4gPSA1DQoNCiMgR2VuZXJhdGUgbXVsdGlwbGUgc2FtcGxlcyBmcm9tIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbg0Kbi5zYW1wbGVzIDwtIDEwMDAwDQpleHAubWVhbnMgPC0gcmVwbGljYXRlKG4uc2FtcGxlcywgbWVhbihyZXhwKG4ubGFyZ2UsIHJhdGUgPSBsYW1iZGEpKSkNCg0KIyBDb21wYXJlIHdpdGggbm9ybWFsIGFwcHJveGltYXRpb24NCnRoZW9yZXRpY2FsLm1lYW4gPC0gMS9sYW1iZGEgICMgNQ0KdGhlb3JldGljYWwuc2QgPC0gKDEvbGFtYmRhKS9zcXJ0KG4ubGFyZ2UpICAjIDUvc3FydCg1MCkNCg0KdGhlb3J5LmRlbnNpdHkgPC0gZG5vcm0oeC52YWxzLCBtZWFuID0gdGhlb3JldGljYWwubWVhbiwgc2QgPSB0aGVvcmV0aWNhbC5zZCkNCnRoZW9yeS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LnZhbHMsIGRlbnNpdHkgPSB0aGVvcnkuZGVuc2l0eSkNCg0KIyBPcHRpb24gMTogVXNlIG9ubHkgc3RhdF9mdW5jdGlvbiBmb3IgdGhlb3JldGljYWwgY3VydmUgKFJlY29tbWVuZGVkKQ0KZ2cuY2x0IDwtIGdncGxvdChkYXRhLmZyYW1lKG1lYW4gPSBleHAubWVhbnMpLCBhZXMoeCA9IG1lYW4pKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksIGJpbnMgPSA1MCwgYWxwaGEgPSAwLjcsIGZpbGwgPSAibGlnaHRncmVlbiIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSB0aGVvcnkuZGYsIGFlcyh4ID0geCwgeSA9IGRlbnNpdHkpLCANCiAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICJBc3ltcHRvdGljIFNhbXBsaW5nIERpc3RyaWJ1dGlvbiBvZiBTYW1wbGUgTWVhbiBcbkV4cG9uZW50aWFsIFBvcHVsYXRpb24gKG4gPSA1MCkiLA0KICAgICAgIHggPSAiU2FtcGxlIE1lYW4iLCB5ID0gIkRlbnNpdHkiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCiNnZy5jbHQNCmdncGxvdGx5KGdnLmNsdCkNCmBgYA0KDQoNCg0KDQoNCg0KIyBTdHVkZW50J3MgdC1EaXN0cmlidXRpb24NCg0KV2hlbiBwb3B1bGF0aW9uIHZhcmlhbmNlICRcc2lnbWFeMiQgaXMgdW5rbm93biBhbmQgZXN0aW1hdGVkIGJ5IHNhbXBsZSB2YXJpYW5jZSAkU14yJDoNCg0KJCQNClQgPSBcZnJhY3tcYmFye1h9LVxtdX17Uy9cc3FydHtufX0gXHRvICB0X3tuLTF9DQokJA0KDQp3aGVyZSAkU14yID0gXGZyYWN7MX17bi0xfVxzdW1fe2k9MX1ebiAoWF9pIC0gXGJhcntYfSleMiQNCg0KDQoNCioqRXhhbXBsZSoqOg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCm4gPC0gMTANCm11IDwtIDUNCnNpZ21hIDwtIDINCg0KIyBHZW5lcmF0ZSB0LXN0YXRpc3RpY3MNCm4uc2FtcGxlcyA8LSAxMDAwMA0KdC5zdGF0cyA8LSBudW1lcmljKG4uc2FtcGxlcykNCg0KZm9yKGkgaW4gMTpuLnNhbXBsZXMpIHsNCiAgc2FtcGxlLmRhdGEgPC0gcm5vcm0obiwgbXUsIHNpZ21hKQ0KICB4LmJhciA8LSBtZWFuKHNhbXBsZS5kYXRhKQ0KICBzIDwtIHNkKHNhbXBsZS5kYXRhKQ0KICB0LnN0YXRzW2ldIDwtICh4LmJhciAtIG11KSAvIChzL3NxcnQobikpDQp9DQoNCiMgQ29tcGFyZSB3aXRoIHRoZW9yZXRpY2FsIHQtZGlzdHJpYnV0aW9uDQp4LnZhbHMgPC0gc2VxKC00LCA0LCBsZW5ndGgub3V0ID0gMjAwKQ0KdGhlb3JldGljYWwudCA8LSBkdCh4LnZhbHMsIGRmID0gbi0xKQ0KdGhlb3JldGljYWwubm9ybWFsIDwtIGRub3JtKHgudmFscykNCg0KY29tcGFyaXNvbi5kZiA8LSBkYXRhLmZyYW1lKA0KICB4ID0gcmVwKHgudmFscywgMiksDQogIGRlbnNpdHkgPSBjKHRoZW9yZXRpY2FsLnQsIHRoZW9yZXRpY2FsLm5vcm1hbCksDQogIGRpc3RyaWJ1dGlvbiA9IHJlcChjKCJ0KDkpIiwgIk4oMCwxKSIpLCBlYWNoID0gbGVuZ3RoKHgudmFscykpDQopDQoNCnQucGx0IDwtIGdncGxvdChjb21wYXJpc29uLmRmLCBhZXMoeCA9IHgsIHkgPSBkZW5zaXR5LCBjb2xvciA9IGRpc3RyaWJ1dGlvbikpICsNCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAidC1EaXN0cmlidXRpb24gdnMgTm9ybWFsIERpc3RyaWJ1dGlvbiIsDQogICAgICAgeCA9ICJWYWx1ZSIsIHkgPSAiRGVuc2l0eSIpICsNCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDM1LCByID0gMjAsIGIgPSAzMCwgbCA9IDMwLCB1bml0ID0gInB0IikpICsNCiAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJyZWQiLCAiYmx1ZSIpKQ0KZ2dwbG90bHkodC5wbHQpDQpgYGANCg0KDQoNCiMgU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIFNhbXBsZSBQcm9wb3J0aW9uDQoNCjMuMSBFeGFjdCBEaXN0cmlidXRpb24NCg0KRm9yIGEgYmlub21pYWwgcG9wdWxhdGlvbiB3aXRoIHN1Y2Nlc3MgcHJvYmFiaWxpdHkgJHAkLCB0aGUgc2FtcGxlIHByb3BvcnRpb24gJFxoYXR7cH0gPSBYL24kIHdoZXJlICRYIFxzaW0gQmlub21pYWwobixwKSQuDQoNClRoZSBleGFjdCBkaXN0cmlidXRpb24gaXMgc2ltcGx5IHRoZSBwcm9iYWJpbGl0eSBtYXNzIGZ1bmN0aW9uIG9mIGEgYmlub21pYWwgZGlzdHJpYnV0aW9uIHdpdGggbiB0cmlhbHMgYW5kIHN1Y2Nlc3MgcHJvYmFiaWxpdHkgJHAkOg0KDQokJA0KUChcaGF0e3B9ID1rL24pPVAoWCA9IGspPVxmcmFje24hfXtrIShuLWspIX0gcF5rICgx4oiScClee24ta30sIFwgXCBrID0gMCwgMSwgMiwgXGNkb3RzLCBuLg0KJCQgDQoNCg0KIyMgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24NCg0KQnkgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLCBhcyAkbiBcdG8gXGluZnR5JDoNCg0KJCQNClxoYXR7cH0gXHRvIE5cbGVmdChwLCBcc3FydHtcZnJhY3twKDEtcCl9e259fSBccmlnaHQpDQokJA0KDQoqKkV4YW1wbGUqKjoNCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpuIDwtIDEwMA0KcCA8LSAwLjMNCg0KIyBHZW5lcmF0ZSBzYW1wbGUgcHJvcG9ydGlvbnMNCm4uc2FtcGxlcyA8LSAxMDAwMA0Kc2FtcGxlLnByb3BzIDwtIHJlcGxpY2F0ZShuLnNhbXBsZXMsIHJiaW5vbSgxLCBuLCBwKS9uKQ0KDQojIENvbXBhcmUgd2l0aCBub3JtYWwgYXBwcm94aW1hdGlvbg0KdGhlb3JldGljYWwubWVhbiA8LSBwDQp0aGVvcmV0aWNhbC5zZCA8LSBzcXJ0KHAqKDEtcCkvbikNCg0KeC52YWxzIDwtIHNlcSgwLDAuNiwgbGVuZ3RoPTEwMCkNCnRoZW9yeS5kZW5zaXR5IDwtIGRub3JtKHgudmFscywgbWVhbiA9IHRoZW9yZXRpY2FsLm1lYW4sIHNkID0gdGhlb3JldGljYWwuc2QpDQp0aGVvcnkuZGYgPC0gZGF0YS5mcmFtZSh4ID0geC52YWxzLCBkZW5zaXR5ID0gdGhlb3J5LmRlbnNpdHkpDQoNCmJpbm9tLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZShwcm9wID0gc2FtcGxlLnByb3BzKSwgYWVzKHggPSBwcm9wKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlucyA9IDMwLCBhbHBoYSA9IDAuNywgZmlsbCA9ICJza3libHVlIikgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHRoZW9yeS5kZiwgYWVzKHggPSB4LCB5ID0gZGVuc2l0eSksIA0KICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSkgKw0KICAjc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgDQogICMgICAgICAgICAgICAgIGFyZ3MgPSBsaXN0KG1lYW4gPSB0aGVvcmV0aWNhbF9tZWFuLCBzZCA9IHRoZW9yZXRpY2FsX3NkKSwNCiAgIyAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICJTYW1wbGluZyBEaXN0cmlidXRpb24gb2YgU2FtcGxlIFByb3BvcnRpb24iLA0KICAgICAgIHN1YnRpdGxlID0gInAgPSAwLjMsIG4gPSAxMDAiLA0KICAgICAgIHggPSAiU2FtcGxlIFByb3BvcnRpb24iLCB5ID0gIkRlbnNpdHkiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCmdncGxvdGx5KGJpbm9tLnBsdCkNCmBgYA0KDQoNCiMgQ2hpLVNxdWFyZSBEaXN0cmlidXRpb24NCg0KRm9yICRaXzEsIFpfMiwgXGxkb3RzLCBaX2sgXHN0YWNrcmVse2lpZH17XHNpbX0gTigwLDEpJCwgdXNpbmcgbW9tZW50IGdlbmVyYXRpbmcgZnVuY3Rpb24sIHdlIGNhbiBzaG93IHRoYXQNCg0KJCQNClE9XHN1bV97aT0xfV5rIFpfaV4yIFx0byBcY2hpX2teMi4NCiQkDQogDQoNCkZvciBzYW1wbGUgdmFyaWFuY2UgZnJvbSBub3JtYWwgcG9wdWxhdGlvbjoNCg0KJCQNClxmcmFjeyhuLTEpU14yfXtcc2lnbWFeMn0gXHRvIFxjaGlfe24tMX1eMg0KJCQNCioqUHJvb2YqKjogV2UgcHJvdmUgdGhpcyBpbiBzZXZlcmFsIHN0ZXBzOg0KDQpXZSBzaG93IHRoYXQgZm9yICRYXzEsIFxkb3RzLCBYX24gXGlpZCBOKFxtdSwgXHNpZ21hXjIpJCwgd2l0aA0KDQokJA0KU14yID0gXGZyYWN7MX17bi0xfSBcc3VtX3tpPTF9Xm4gKFhfaSAtIFxiYXJ7WH0pXjIsIFxxdWFkIFxiYXJ7WH0gPSBcZnJhY3sxfXtufSBcc3VtX3tpPTF9Xm4gWF9pLA0KJCQNCg0Kd2UgaGF2ZQ0KDQokJA0KXGZyYWN7KG4tMSlTXjJ9e1xzaWdtYV4yfSBcc2ltIFxjaGlfe24tMX1eMi4NCiQkDQoNCioqU3RlcCAxOiBTdGFuZGFyZGl6ZSBhbmQgZGVmaW5lIG5vdGF0aW9uKioNCg0KTGV0ICRaX2kgPSBcZnJhY3tYX2kgLSBcbXV9e1xzaWdtYX0gXHNpbSBOKDAsMSkkLCBpLmkuZC4gVGhlbg0KDQokJA0KXGJhcntafSA9IFxmcmFjezF9e259IFxzdW1fe2k9MX1ebiBaX2kgPSBcZnJhY3tcYmFye1h9IC0gXG11fXtcc2lnbWF9Lg0KJCQNCg0KV2UgY2FuIHdyaXRlOg0KDQokJA0KXHN1bV97aT0xfV5uIChYX2kgLSBcYmFye1h9KV4yID0gXHNpZ21hXjIgXHN1bV97aT0xfV5uIChaX2kgLSBcYmFye1p9KV4yLg0KJCQNCg0KU28NCg0KJCQNClxmcmFjeyhuLTEpU14yfXtcc2lnbWFeMn0gPSBcZnJhY3tcc3VtX3tpPTF9Xm4gKFhfaSAtIFxiYXJ7WH0pXjJ9e1xzaWdtYV4yfSA9IFxzdW1fe2k9MX1ebiAoWl9pIC0gXGJhcntafSleMi4NCiQkDQoNCioqU3RlcCAyOiBPcnRob2dvbmFsIHRyYW5zZm9ybWF0aW9uKioNCg0KTGV0IFwoIFxtYXRoYmZ7Wn0gPSAoWl8xLCBcZG90cywgWl9uKV5UIFwpLiBDaG9vc2UgYW4gXCggbiBcdGltZXMgbiBcKSBvcnRob2dvbmFsIG1hdHJpeCBcKCBRIFwpIHdob3NlIGZpcnN0IHJvdyBpcyBcKCBcbGVmdCggXGZyYWN7MX17XHNxcnR7bn19LCBcZG90cywgXGZyYWN7MX17XHNxcnR7bn19IFxyaWdodCkgXCkuIERlZmluZQ0KDQokJA0KXG1hdGhiZntZfSA9IFEgXG1hdGhiZntafS4NCiQkDQoNClRoZW46DQoNCiogJFlfMSA9IFxmcmFjezF9e1xzcXJ0e259fSBcc3VtX3tpPTF9Xm4gWl9pID0gXHNxcnR7bn0gXCwgXGJhcntafSQuDQoqIFNpbmNlICRRJCBpcyBvcnRob2dvbmFsIGFuZCAkXG1hdGhiZntafSBcc2ltIE4oMCwgSV9uKSQsIHdlIGhhdmUgJFxtYXRoYmZ7WX0gXHNpbSBOKDAsIElfbikkIGFzIHdlbGwsIHNvICRZXzEsIFxkb3RzLCBZX24kIGFyZSBpLmkuZC5cICROKDAsMSkkLg0KDQoNCioqU3RlcCAzOiBFeHByZXNzIHN1bSBvZiBzcXVhcmVzIGluIHRlcm1zIG9mIFwoIFlfaiBcKSoqDQoNCk9ydGhvZ29uYWxpdHkgaW1wbGllczoNCg0KJCQNClxzdW1fe2k9MX1ebiBaX2leMiA9IFxzdW1fe2o9MX1ebiBZX2peMi4NCiQkDQoNCkFsc28sDQoNCiQkDQpcc3VtX3tpPTF9Xm4gKFpfaSAtIFxiYXJ7Wn0pXjIgPSBcc3VtX3tpPTF9Xm4gWl9pXjIgLSBuIFxiYXJ7Wn1eMi4NCiQkDQoNCkJ1dCAkbiBcYmFye1p9XjIgPSBZXzFeMiQsIHNvDQoNCiQkDQpcc3VtX3tpPTF9Xm4gKFpfaSAtIFxiYXJ7Wn0pXjIgPSBcc3VtX3tqPTF9Xm4gWV9qXjIgLSBZXzFeMiA9IFxzdW1fe2o9Mn1ebiBZX2peMi4NCiQkDQoNCioqU3RlcCA0OiBEaXN0cmlidXRpb24qKg0KDQpTaW5jZSAkWV8yLCBcZG90cywgWV9uJCBhcmUgaS5pLmQuXCAkTigwLDEpJCwgd2UgaGF2ZQ0KDQokJA0KXHN1bV97aj0yfV5uIFlfal4yIFxzaW0gXGNoaV97bi0xfV4yLg0KJCQNCg0KVGh1cw0KDQokJA0KXGZyYWN7KG4tMSlTXjJ9e1xzaWdtYV4yfSA9IFxzdW1fe2k9MX1ebiAoWl9pIC0gXGJhcntafSleMiA9IFxzdW1fe2o9Mn1ebiBZX2peMiBcc2ltIFxjaGlfe24tMX1eMi4NCiQkDQoNCioqU3RlcCA1OiBJbmRlcGVuZGVuY2UgZnJvbSBcKCBcYmFye1h9IFwpKioNCg0KU2luY2UgJFlfMSA9IFxzcXJ0e259IFxiYXJ7Wn0kIGlzIGluZGVwZW5kZW50IG9mICRZXzIsIFxkb3RzLCBZX24kLCBpdCBmb2xsb3dzIHRoYXQgJFxiYXJ7WH0kIGlzIGluZGVwZW5kZW50IG9mICRTXjIkLiBUaGF0IGlzLA0KDQokJA0KXGJveGVke1xmcmFjeyhuLTEpU14yfXtcc2lnbWFeMn0gXHRvIFxjaGlfe24tMX1eMn0NCiQkDQoNCioqRXhhbXBsZSoqOiBUaGUgJFxjaGleMiQgZGlzdHJpYnV0aW9uIGlzIGRlcml2ZWQgZnJvbSB0aGUgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gV2Ugc2ltdWxhdGUgc3RhbmRhcmQgbm9ybWFsIHJhbmRvbSBudW1iZXJzIGFuZCB0aGVuIHRyYW5zZm9ybSB0aGVtIGludG8gJFxjaGleMiQgcmFuZG9tIHZhcmlhYmxlcyBiYXNlZCBvbiB0aGUgZGVyaXZhdGlvbnMgYWJvdmUuIEEgaGlzdG9ncmFtIHdpbGwgYmUgcGxvdHRlZCBhbmQgb3ZlcmxhaWQgd2l0aCB0aGUgdGhlb3JldGljYWwgJFxjaGleMiQgZGVuc2l0eSBjdXJ2ZS4NCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpuIDwtIDEwDQpzaWdtYSA8LSAyDQoNCiMgR2VuZXJhdGUgY2hpLXNxdWFyZSBzdGF0aXN0aWNzDQpuLnNhbXBsZXMgPC0gMTAwMDANCmNoaXNxLnN0YXRzIDwtIG51bWVyaWMobi5zYW1wbGVzKQ0KDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICBzYW1wbGUuZGF0YSA8LSBybm9ybShuLCAwLCBzaWdtYSkNCiAgY2hpc3Euc3RhdHNbaV0gPC0gc3VtKChzYW1wbGUuZGF0YS9zaWdtYSleMikNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgY2hpLXNxdWFyZQ0KeC52YWxzIDwtIHNlcSgwLCAzMCwgbGVuZ3RoLm91dCA9IDIwMCkNCnRoZW9yZXRpY2FsLmNoaXNxIDwtIGRjaGlzcSh4LnZhbHMsIGRmID0gbikNCnRoZW9yeS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LnZhbHMsIGRlbnNpdHkgPSB0aGVvcmV0aWNhbC5jaGlzcSkNCg0KY2hpLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZSh4ID0gY2hpc3Euc3RhdHMpLCBhZXMoeCA9IHgpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gNTAsIGFscGhhID0gMC43LCBmaWxsID0gInN0ZWVsYmx1ZSIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSB0aGVvcnkuZGYsIGFlcyh4ID0geCwgeSA9IGRlbnNpdHkpLCANCiAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgI3N0YXRfZnVuY3Rpb24oZnVuID0gZGNoaXNxLCBhcmdzID0gbGlzdChkZiA9IG4pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIkNoaS1TcXVhcmUgRGlzdHJpYnV0aW9uIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJTdW0gb2Ygc3F1YXJlZCBzdGFuZGFyZCBub3JtYWxzIiwNCiAgICAgICB4ID0gIlZhbHVlIiwgeSA9ICJEZW5zaXR5IikgKw0KICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSAzNSwgciA9IDIwLCBiID0gMzAsIGwgPSAzMCwgdW5pdCA9ICJwdCIpKQ0KZ2dwbG90bHkoY2hpLnBsdCkNCmBgYA0KDQojIEYtRGlzdHJpYnV0aW9uDQoNCkZvciB0d28gaW5kZXBlbmRlbnQgY2hpLXNxdWFyZSByYW5kb20gdmFyaWFibGVzOg0KDQokJA0KRiA9IFxmcmFje1VfMS9kXzF9e1VfMi9kXzJ9IFx0byBGX3tkXzEsIGRfMn0NCiQkDQogDQp3aGVyZSAkVV8xIFxzaW0gXGNoaV4yX3tkXzF9JCBhbmQgJFVfMiBcc2ltIFxjaGleMl97ZF8yfSQuDQoNCg0KDQpGIGRpc3RyaWJ1dGlvbiBpcyB1c2VkIGZvciBjb21wYXJpbmcgdmFyaWFuY2VzOiAkXGZyYWN7U18xXjIvXHNpZ21hXzFeMn17U18yXjIvXHNpZ21hXzJeMn0gXHNpbSBGX3tuXzEtMSxuXzItMX0kLiBGb3IgZXhhbXBsZSwgaWYgd2UgdGVzdA0KDQokJA0KSF8wOiBcIFxzaWdtYV8xID0gXHNpZ21hXzIgXCBcIFwgdi5zLiBcIFwgXCBIX2E6ICBcc2lnbWFfMSBcbmUgXHNpZ21hXzINCiQkDQpUaGUgdGVzdCBzdGF0aXN0aWMNCg0KJCQNClRTID0gXGZyYWN7U18xXjJ9e1NfMl4yfSBcdG8gRl97bl8xLTEsIG5fMi0xfQ0KJCQNCg0KDQoqKkV4YW1wbGUqKjogVGhlIEYgZGlzdHJpYnV0aW9uIGlzIGRpcmVjdGx5IGRlZmluZWQgYmFzZWQgb24gdHdvIGluZGVwZW5kZW50ICRcY2hpXjIkIGRpc3RyaWJ1dGlvbnMsIHdoaWNoIGFyZSB0aGVtc2VsdmVzIGRlcml2ZWQgZnJvbSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9ucy4gVGhlcmVmb3JlLCB3ZSBjb3VsZCBnZW5lcmF0ZSBkYXRhIGZyb20gbm9ybWFsIGRpc3RyaWJ1dGlvbnMgYW5kIHRoZW4gdHJhbnNmb3JtIHRoZW0gaW50byBGIHJhbmRvbSB2YXJpYWJsZXMuIFRvIGtlZXAgdGhlIHByb2Nlc3Mgc2ltcGxlLCB3ZSBnZW5lcmF0ZSBkYXRhIGRpcmVjdGx5IGZyb20gJFxjaGleMiQgZGlzdHJpYnV0aW9ucy4NCg0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQpkZjEgPC0gMTANCmRmMiA8LSAxNQ0KDQojIEdlbmVyYXRlIEYgc3RhdGlzdGljcw0Kbi5zYW1wbGVzIDwtIDEwMDAwDQpmLnN0YXRzIDwtIG51bWVyaWMobi5zYW1wbGVzKQ0KDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICB1MSA8LSByY2hpc3EoMSwgZGYxKQ0KICB1MiA8LSByY2hpc3EoMSwgZGYyKQ0KICBmLnN0YXRzW2ldIDwtICh1MS9kZjEpIC8gKHUyL2RmMikNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgRi1kaXN0cmlidXRpb24NCngudmFscyA8LSBzZXEoMCwgNSwgbGVuZ3RoLm91dCA9IDIwMCkNCnRoZW9yZXRpY2FsLmYgPC0gZGYoeC52YWxzLCBkZjEsIGRmMikNCnRoZW9yeS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LnZhbHMsIGRlbnNpdHkgPSB0aGVvcmV0aWNhbC5mKQ0KDQoNCg0KDQpmLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZSh4ID0gZi5zdGF0cyksIGFlcyh4ID0geCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSA1MCwgYWxwaGEgPSAwLjcsIGZpbGwgPSAicHVycGxlMyIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSB0aGVvcnkuZGYsIGFlcyh4ID0geCwgeSA9IGRlbnNpdHkpLCANCiAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDUpKSArDQogIGxhYnModGl0bGUgPSBwYXN0ZSgiRi1EaXN0cmlidXRpb24gXG4gRigiLCBkZjEsICIsIiwgZGYyLCAiKSIsIHNlcCA9ICIiKSwNCiAgICAgICB4ID0gIlZhbHVlIiwgeSA9ICJEZW5zaXR5IikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDM1LCByID0gMjAsIGIgPSAzMCwgbCA9IDMwLCB1bml0ID0gInB0IikpDQpnZ3Bsb3RseShmLnBsdCkNCmBgYA0KDQoNCg0KIyBTdW1tYXJ5IG9mIEtleSBSZWxhdGlvbnNoaXBzDQoNCnxTdGF0aXN0aWMJfCBFeGFjdCBEaXN0cmlidXRpb24gfAlBc3ltcHRvdGljIERpc3RyaWJ1dGlvbiB8CUNvbmRpdGlvbnMgfA0KfDotLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS18DQp8ICRcYmFye1h9JAl8ICROKFxtdSwgXHNpZ21hXjIvbikkfCAJJE4oXG11LCBcc2lnbWFeMi9uKSR8IAlOb3JtYWwgcG9wdWxhdGlvbiBvciBsYXJnZSBufCANCnwgJFxmcmFje1xiYXJ7WH0tXG11fXtTL1xzcXJ0e259fSR8IAkkdF97bi0xfSQJfCAkTigwLDEpJHwgCU5vcm1hbCBwb3B1bGF0aW9ufCANCnwgJFxoYXR7cH0kCXwgJEJpbm9taWFsKG4scCkvbiQJfCAkTihwLCBwKDEtcCkvbikkfCAJJG5wLCBuKDEtcCkgXGdlcSA1JHwgDQp8ICRcZnJhY3sobi0xKVNeMn17XHNpZ21hXjJ9JAl8ICRcY2hpXjJfe24tMX0kIHwtCXwgTm9ybWFsIHBvcHVsYXRpb258IA0KfCAkXGZyYWN7U18xXjIvXHNpZ21hXzFeMn17U18yXjIvXHNpZ21hXzJeMn0kfCAkRl97bl8xLTEsbl8yLTF9JHwgCS0JfCBOb3JtYWwgcG9wdWxhdGlvbnN8IA0KDQoNCioqQ29uY2x1c2lvbioqDQoNCiogVW5kZXJzdGFuZGluZyBzYW1wbGluZyBkaXN0cmlidXRpb25zIGlzIGZ1bmRhbWVudGFsIHRvIHN0YXRpc3RpY2FsIGluZmVyZW5jZToNCg0KKiBFeGFjdCBkaXN0cmlidXRpb25zIHByb3ZpZGUgcHJlY2lzZSByZXN1bHRzIHdoZW4gYXNzdW1wdGlvbnMgYXJlIG1ldA0KDQoqIEFzeW1wdG90aWMgZGlzdHJpYnV0aW9ucyBvZmZlciBhcHByb3hpbWF0aW9ucyBmb3IgbGFyZ2Ugc2FtcGxlcw0KDQoqIFRoZSBjaG9pY2UgYmV0d2VlbiBleGFjdCBhbmQgYXN5bXB0b3RpYyBtZXRob2RzIGRlcGVuZHMgb24gc2FtcGxlIHNpemUsIGRpc3RyaWJ1dGlvbmFsIGFzc3VtcHRpb25zLCBhbmQgdGhlIHNwZWNpZmljIHBhcmFtZXRlciBiZWluZyBlc3RpbWF0ZWQNCg0KKiBNb2Rlcm4gY29tcHV0aW5nIGFsbG93cyBmb3IgZW1waXJpY2FsIHZlcmlmaWNhdGlvbiBvZiB0aGVzZSB0aGVvcmV0aWNhbCByZXN1bHRzDQoNCg0KVGhlc2UgZGlzdHJpYnV0aW9ucyBmb3JtIHRoZSB0aGVvcmV0aWNhbCBmb3VuZGF0aW9uIGZvciBoeXBvdGhlc2lzIHRlc3RpbmcsIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCBhbmQgbWFueSBvdGhlciBzdGF0aXN0aWNhbCBwcm9jZWR1cmVzLg0KDQoNCg0KDQoNCg==